package com.huidu.bitrade.service;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.Maps;
import com.huidu.bitrade.hdwallet.data.WithdrawData;
import com.huidu.bitrade.hdwallet.properties.HdWalletProperties;
import com.huidu.bitrade.hdwallet.data.RequestWalletData;
import com.huidu.bitrade.hdwallet.data.RequestWalletSignData;
import com.huidu.bitrade.hdwallet.SignUtil;
import com.spark.bipay.constant.CoinTransferType;
import com.spark.bipay.constant.CoinType;
import com.spark.bipay.constant.Contract;
import com.spark.bipay.entity.Address;
import com.spark.bipay.entity.Trade;
import com.spark.bipay.http.ResponseMessage;
import com.spark.bipay.http.client.BiPayClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Map;

@Slf4j
@Service
public class BiPayService {
    @Autowired
    private BiPayClient biPayClient;
    @Value("${bipay.callback.url}")
    private String callbackUrl;
    @Autowired
    private HdWalletProperties hdWalletProperties;


    /**
     * 调用udun钱包
     * @param coinType
     * @param memberId
     * @return
     */
    public Address createCoinAddress(String coinType, String memberId) {
        try {
            ResponseMessage<Address> resp = biPayClient.createCoinAddress(coinType, callbackUrl, memberId, null);
            if (resp.getCode() != 200) {
                log.error("createCoinAddress error coinType:" + coinType + " memberId:" + memberId + " resp:" + JSONObject.toJSONString(resp));
                return null;
            }
            return resp.getData();
        } catch (Exception e) {
            log.error("createCoinAddress coinType:" + coinType + " memberId:" + memberId, e);
        }
        return null;
    }

    /**
     * 调用hd钱包
     * @param coinType 是币种网络
     * @param memberId
     * @return
     */
    public String createCoinAddressByHdWallet(String coinType, String memberId) {
        try {
            RequestWalletData requestWalletData = new RequestWalletData();
            requestWalletData.setCoinType(coinType); //BSC TRON
            requestWalletData.setMemberId(memberId);
            requestWalletData.setMerchantCode(hdWalletProperties.getMerchantCode());
            requestWalletData.setAppKey(hdWalletProperties.getAppKey());
            requestWalletData.setAppSecret(hdWalletProperties.getAppSecret());

            String body = JSONObject.toJSONString(requestWalletData);
            RequestWalletSignData data = wrapperData(body);
            String responseJson = HttpUtil.post(hdWalletProperties.getGenAddressUrl(), JSONObject.toJSONString(data));
            log.info("调用hd wallet生成用户钱包地址响应：{}",responseJson);
            JSONObject jsonObject = JSONObject.parseObject(responseJson);
            Integer code = jsonObject.getInteger("code");
            if(code == 0){
                return jsonObject.getString("data");
            }
        } catch (Exception e) {
            log.error("createCoinAddress coinType:" + coinType + " memberId:" + memberId, e);
        }
        return null;
    }

    private RequestWalletSignData wrapperData(String body){
        String timestamp = System.currentTimeMillis()+"";
        String nonce = SignUtil.getNonceString(1);
        String sign = SignUtil.sign(hdWalletProperties.getApiKey(), timestamp, nonce, body);
        RequestWalletSignData data = new RequestWalletSignData();
        data.setBody(body);
        data.setSign(sign);
        data.setNonce(nonce);
        data.setTimestamp(timestamp);
        return data;
    }

    /**
     * 提币
     * @param orderId
     * @param amount
     * @param coinType
     * @param subCoinType
     * @param address
     * @param memo
     * @return
     */
    public ResponseMessage<String> transfer(String orderId, BigDecimal amount, CoinType coinType, String subCoinType, String address, String memo) {
        try {
            return biPayClient.transfer(orderId, amount, coinType.getCode(), subCoinType, address, callbackUrl, memo);
        } catch (Exception e) {
            log.error("transfer "+e.getMessage(),e );
        }
        return ResponseMessage.error("Failed to submit currency transfer");
    }

//    public ResponseMessage<String> withdraw(String orderId, BigDecimal amount, CoinTransferType coinTransferType, String address, String memo) {
//        try {
//            return biPayClient.withdraw(orderId, amount, coinTransferType, address, callbackUrl, memo);
//        } catch (Exception e) {
//            log.error("transfer "+e.getMessage(),e );
//        }
//        return ResponseMessage.error("Failed to submit currency transfer");
//    }

    public ResponseMessage<String> withdraw(String orderId, BigDecimal amount, CoinTransferType coinTransferType, String address, String memo) {
        try{
            Map<String, Object> meta = Maps.newHashMap();
            meta.put("businessId",orderId);
            WithdrawData data = WithdrawData.builder()
                    .orderId(orderId)
                    .merchantCode(hdWalletProperties.getMerchantCode())
                    .address(address)
                    .number(amount)
                    .chainName(coinTransferType.getChain())
                    .contractAddress(coinTransferType.getContract())
                    .appKey(hdWalletProperties.getAppKey())
                    .appSecret(hdWalletProperties.getAppSecret())
                    .meta(JSON.toJSONString(meta))
                    .build();
            RequestWalletSignData requestWalletSignData = wrapperData(JSON.toJSONString(data));
            String responseJson = HttpUtil.post(hdWalletProperties.getWithdrawUrl(), JSONObject.toJSONString(requestWalletSignData));
            log.info("调用hd 钱包接口提现：{}",responseJson);
            JSONObject json = JSONObject.parseObject(responseJson);
            Integer code = json.getInteger("code");
            if(code == 0){
                return ResponseMessage.success(json.getInteger("code"), json.getString("message"));
            }else{
                return ResponseMessage.error(json.getInteger("code"), json.getString("message"));
            }
        }catch (Exception e){
            return ResponseMessage.error("提现调用失败");
        }
    }

    public String code2Coin(Trade trade) {
        CoinType type = CoinType.codeOf(Integer.parseInt(trade.getMainCoinType()));
        assert type != null;
        if (trade.getCoinType().equals(Contract.Erc20_USDT))//EUSDT
            return "USDT";
        if (trade.getCoinType().equals(Contract.Trc20_USDT))//TUSDT
            return "TUSDT";
        if (trade.getCoinType().equals(Contract.XRP))//XRP
            return "XRP";
        if (trade.getCoinType().equals(Contract.CHZ))//CHZ
            return "CHZ";
        if (trade.getCoinType().equals(Contract.UNI))//UNI
            return "UNI";
        if (trade.getCoinType().equals(Contract.HT))//HT
            return "HT";
        if (trade.getCoinType().equals(Contract.RLC))//RLC
            return "RLC";
        if (trade.getCoinType().equals(Contract.CRV))//CRV
            return "CRV";
        if (trade.getCoinType().equals(Contract.AAVE))//AAVE
            return "AAVE";
        if (trade.getCoinType().equals(Contract.BAL))//BAL
            return "BAL";
        if (trade.getCoinType().equals(Contract.HDC))//HDC
            return "HDC";
        if (trade.getCoinType().equals(Contract.HDZ))//HDZ
            return "HDZ";
        if (trade.getCoinType().equals(Contract.CNHD))//CNHD
            return "CNHD";
        if (trade.getCoinType().equals(Contract.ZYDC))//ZYDC
            return "ZYDC";
        if (trade.getCoinType().equals(Contract.DSH))//DSH
            return "DSH";
        if (trade.getCoinType().equals(Contract.ALEOTZ))//ALEOTZ
            return "ALEOTZ";
        return type.getUnit();
    }

    public String code2CoinByHd(String coinType) {
        assert coinType != null;
        if (coinType.equalsIgnoreCase(Contract.Erc20_USDT))//EUSDT
            return "USDT";
        if (coinType.equalsIgnoreCase(Contract.Trc20_USDT))//TUSDT
            return "TUSDT";
        if (coinType.equalsIgnoreCase(Contract.XRP))//XRP
            return "XRP";
        if (coinType.equalsIgnoreCase(Contract.CHZ))//CHZ
            return "CHZ";
        if (coinType.equalsIgnoreCase(Contract.UNI))//UNI
            return "UNI";
        if (coinType.equalsIgnoreCase(Contract.HT))//HT
            return "HT";
        if (coinType.equalsIgnoreCase(Contract.RLC))//RLC
            return "RLC";
        if (coinType.equalsIgnoreCase(Contract.CRV))//CRV
            return "CRV";
        if (coinType.equalsIgnoreCase(Contract.AAVE))//AAVE
            return "AAVE";
        if (coinType.equalsIgnoreCase(Contract.BAL))//BAL
            return "BAL";
        if (coinType.equalsIgnoreCase(Contract.HDC))//HDC
            return "HDC";
        if (coinType.equalsIgnoreCase(Contract.HDZ))//HDZ
            return "HDZ";
        if (coinType.equalsIgnoreCase(Contract.CNHD))//CNHD
            return "CNHD";
        if (coinType.equals(Contract.ZYDC))//ZYDC
            return "ZYDC";
        if (coinType.equalsIgnoreCase(Contract.DSH))//DSH
            return "DSH";
        if (coinType.equalsIgnoreCase(Contract.ALEOTZ))//ALEOTZ
            return "ALEOTZ";
        return null;
    }
}
